package 多线程2;
//wait和notify的使用
public class TestDemo3 {
    static class WaitTask implements Runnable{
        private Object locker = null;

        public WaitTask(Object locker) {
            this.locker = locker;
        }

        @Override
        public void run() {
            //进行wait线程
            synchronized (locker){
                System.out.println("wait 开始");
                try {
                    //直接调用wait,相当于this.wait(),也就是针对WaitTask对象来进行等待.
                    //但是一会在NotifyTask中要求针对同一个对象来进行通知,然而,,在NotifyTask中
                    //并没有那么容易拿到WaitTask实例
//                wait();
                    locker.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("wait 结束");
            }
        }
    }
    static class NotifyTask implements Runnable{
        private Object locker = null;

        public NotifyTask(Object locker) {
            this.locker = locker;
        }

        @Override
        public void run() {
            //进行noftify线程
            synchronized(locker){
                System.out.println("noftify 开始");
                locker.notify();
                System.out.println("noftify 结束");
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        //为了解决刚才的问题, 专门创建一个对象,去负责进行加锁/通知操作.
        Object locker = new Object();
        Thread t10 = new Thread(new WaitTask(locker));
        Thread t11 = new Thread(new WaitTask(locker));
        Thread t12 = new Thread(new WaitTask(locker));
        Thread t2 = new Thread(new NotifyTask(locker));
        t10.start();
        t11.start();
        t12.start();
        Thread.sleep(3000);
        t2.start();
        //wait开始阻塞等待,然后notify开始,通知完成后,wait所在的线程重新获取到锁

        //一次notify只唤醒一个
        //而notifyAll则是把所有线程都唤醒
        /**
         * 调用notify,相等于就是从阻塞队列中随机挑了一个wait中的PCB放回到就绪队列
         * 调用notify,就是把三个PCB都唤醒了,都放回到就绪队列
         * (虽然把这三个线程都放回去了,但是这三个线程的执行仍然是有先有后的,主要是这三个线程还要竞争锁)
         */

        //wait和sleep的区别
        /**
         * 其实没有明确的关联的关系
         * 1.sleep操作是指定一个固定时间来阻塞等待.wait的话既可以指定时间,也可以无限等待.
         * 2.wait唤醒可以通过notify或者interrupt或者时间到 来唤醒,sleep唤醒通过时间或者interrupt唤醒
         * 3.wait主要的用途就是为了协调线程之间的先后顺序.这样的场景并不适合使用sleep.
         * sleep单纯让该线程休眠.并不涉及到多个线程的配合
         * --
         */
    }
}
